<chapter xml:id="string_utils.h">
<title><tt>__vic/string_utils.h</tt></title>

<p>Miscellaneous strings-related utilities.</p>


<chapter xml:id="trim">
<title><tt>trim</tt> functions</title>

<code-block lang="C++"><![CDATA[
char *trim(char *str);
char *trim_front(char *str);
char *trim_back(char *str);
char *trim(char *str, char ch);
char *trim_front(char *str, char ch);
char *trim_back(char *str, char ch);
char *trim(char *str, const char *set);
char *trim_front(char *str, const char *set);
char *trim_back(char *str, const char *set);

std::string &trim(std::string &str);
std::string &trim_front(std::string &str);
std::string &trim_back(std::string &str);
std::string &trim(std::string &str, char ch);
std::string &trim_front(std::string &str, char ch);
std::string &trim_back(std::string &str, char ch);
std::string &trim(std::string &str, const char *set);
std::string &trim_front(std::string &str, const char *set);
std::string &trim_back(std::string &str, const char *set);

#if __cpp_lib_string_view // C++17
std::string_view trimmed(std::string_view str);
std::string_view trimmed_front(std::string_view str);
std::string_view trimmed_back(std::string_view str);
std::string_view trimmed(std::string_view str, char ch);
std::string_view trimmed_front(std::string_view str, char ch);
std::string_view trimmed_back(std::string_view str, char ch);
std::string_view trimmed(std::string_view str, const char *set);
std::string_view trimmed_front(std::string_view str, const char *set);
std::string_view trimmed_back(std::string_view str, const char *set);
#else // until C++17
std::string trimmed(const std::string &str);
std::string trimmed_left(const std::string &str);
std::string trimmed_right(const std::string &str);
std::string trimmed(const std::string &str, char ch);
std::string trimmed_left(const std::string &str, char ch);
std::string trimmed_right(const std::string &str, char ch);
std::string trimmed(const std::string &str, const char *set);
std::string trimmed_left(const std::string &str, const char *set);
std::string trimmed_right(const std::string &str, const char *set);
#endif
]]></code-block>

<p>The set of functions stripping unwanted characters from the string edges.
Characters to strip can be specified. One can specify single character
<tt>ch</tt> as well as the set of characters <tt>set</tt>. If no characters
is specified, all ASCII-whitespaces are implied. Following naming rules for
the functions are used:</p>
<list style="bulleted">
    <item><tt>trim</tt> - strips from both edges,</item>
    <item><tt>trim_front</tt> - strips from the beginning,</item>
    <item><tt>trim_back</tt> - strips from the end.</item>
</list>

<p>Functions <tt>trim</tt> modify the string in-situ and return the pointer or
reference to it. If the original value should be preserved, <tt>trimmed</tt>
functions should be used.</p>
<list style="bulleted">
    <item><tt>trimmed</tt> - return stripped copy of the string, argument
        itself is not modified.</item>
</list>

<p>The implementation is optimized for common case when the string does not have
anything to trim. In such cases no modifications of the argument are performed,
the function returns immediately after the checks are completed, and the call
is maximally cheap.</p>

<p>All <tt>nullptr</tt> values are treated as an empty string.</p>

<section><title>Example</title>
<code-block lang="C++">
char st1[] = "\t value    \n";

// CHOICE:
__vic::trim(st1);       // result: "value"
__vic::trim_front(st1); // result: "value    \n"
__vic::trim_back(st1);  // result: "\t value"

std::string st2("...value123");

// CHOICE:
// trim dot chars
__vic::trim_front(st1, '.');        // result: "value123"
// trim all digits
__vic::trim_back(st1, "123456789"); // result: "...value"
</code-block>
</section>

</chapter>


<chapter xml:id="sift">
<title><tt>sift()</tt></title>

<code-block lang="C++"><![CDATA[
char *sift(char *str, const char *trash_chars);
std::string &sift(std::string &str, const char *trash_chars);
]]></code-block>

<p>Removes all characters from the set from the string. All <tt>nullptr</tt>
values are treated as an empty string.</p>

<section><title>Example</title>
<code-block lang="C++">
char st[] = "..ab.c..d.e.";
__vic::sift(st, ".");
assert(std::strcmp(st, "abcde") == 0);
</code-block>
</section>

</chapter>


<chapter xml:id="sift_if">
<title><tt>sift_if()</tt></title>

<code-block lang="C++"><![CDATA[
template<class Pred>
char *sift(char *str, Pred pred);
template<class Pred>
std::string &sift(std::string &str, Pred pred);
]]></code-block>

<p>Removes all characters satify the predicate <tt>pred</tt>. All
<tt>nullptr</tt> values are treated as an empty string.</p>

</chapter>


<chapter xml:id="pad_front">
<title><tt>pad_front()</tt></title>

<code-block lang="C++"><![CDATA[
std::string &pad_front(std::string &str, size_t size, char pad_ch = ' ');
char *pad_front(char *str, size_t size, char pad_ch = ' ');
]]></code-block>

<p>Complements the string up to length <tt>size</tt> by adding the required
number of <tt>pad_ch</tt> chars to the beginning. Nothing happens if
<tt>str</tt> length is equal or greather than <tt>size</tt> or the pointer is
null. Returns <tt>str</tt>.</p>

</chapter>


<chapter xml:id="pad_back">
<title><tt>pad_back()</tt></title>

<code-block lang="C++"><![CDATA[
std::string &pad_back(std::string &str, size_t size, char pad_ch = ' ');
char *pad_back(char *str, size_t size, char pad_ch = ' ');
]]></code-block>

<p>Complements the string up to length <tt>size</tt> by adding the required
number of <tt>pad_ch</tt> chars to the end. Nothing happens if
<tt>str</tt> length is equal or greather than <tt>size</tt> or the pointer is
null. Returns
<tt>str</tt>.</p>

</chapter>


<chapter xml:id="starts_with">
<title><tt>starts_with()</tt></title>

<code-block lang="C++"><![CDATA[
bool starts_with(const char *s, char pref);
bool starts_with(const char *s, const char *pref);
bool starts_with(const char *s, const char *pref, size_t pref_len);

#if __cpp_lib_string_view // C++17
bool starts_with(std::string_view s, char pref);
bool starts_with(std::string_view s, std::string_view pref);
bool starts_with(std::string_view s, const char *pref);
#else // until C++17
bool starts_with(const std::string &s, char pref);
bool starts_with(const std::string &s, const char *pref);
bool starts_with(const std::string &s, const std::string &pref);
bool starts_with(const std::string &s, const char *pref, size_t pref_len);
#endif

bool starts_with(const char *s, size_t s_len, char pref);
bool starts_with(const char *s, size_t s_len, const char *pref);
bool starts_with(const char *s, size_t s_len, const char *pref, size_t pref_len);
]]></code-block>

<p>Returns <tt>true</tt> if string <tt>s</tt> starts with the specified
prefix.</p>

</chapter>


<chapter xml:id="ends_with">
<title><tt>ends_with()</tt></title>

<code-block lang="C++"><![CDATA[
#if __cpp_lib_string_view // C++17
bool ends_with(std::string_view s, char suff);
bool ends_with(std::string_view s, std::string_view suff);
#else // until C++17
bool ends_with(const char *s, char suff);
bool ends_with(const char *s, const char *suff);
bool ends_with(const char *s, const char *suff, size_t suff_len);
bool ends_with(const char *s, size_t s_len, const char *suff);

bool ends_with(const std::string &s, char suff);
bool ends_with(const std::string &s, const char *suff);
bool ends_with(const std::string &s, const std::string &suff);
bool ends_with(const std::string &s, const char *suff, size_t suff_len);
#endif

bool ends_with(const char *s, size_t s_len, char suff);
bool ends_with(const char *s, size_t s_len, const char *suff, size_t suff_len);
]]></code-block>

<p>Returns <tt>true</tt> if string <tt>s</tt> ends with the specified
suffix.</p>

</chapter>


</chapter>
